package com.litchi.jms;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.litchi.entity.Bet;
import com.litchi.entity.Lottery;
import com.litchi.persistence.repo.BetRepository;
import com.litchi.utils.LotteryUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.annotation.JmsListener;
import org.springframework.messaging.Message;
import org.springframework.stereotype.Component;

import java.util.stream.IntStream;

/**
 * Created by huash on 2016/5/7.
 */
@Component
@Slf4j
public class ProbabilityUpdateReceiver {

    @Autowired
    private BetRepository betRepository;

    /**
     * When you receive a message, print it out, then shut down the application.
     * Finally, clean up any ActiveMQ server stuff.
     */
    @JmsListener(destination = "lottery-destination", containerFactory = "jmsListenerContainerFactory")
    public void receiveMessage(Message message) {
        System.out.println("Received <" + message + ">");
//        FileSystemUtils.deleteRecursively(new File("activemq-data"));
//        message.getPayload()

        try {
            ObjectMapper m = new ObjectMapper();
            Lottery lottery = m.convertValue(message.getPayload(), Lottery.class);
            log.debug("Received Lottery: " + lottery);
            analysing(lottery);
        } catch (Exception e) {
            log.debug(e.getLocalizedMessage(), e);
        }
    }

    /**
     * @param lottery
     */
    private void analysing(Lottery lottery) {
        calProbabilitiesForAllCombinations(lottery);

        if (LotteryUtils.isLotteryFinished(lottery)) {
            log.info("Lottery Finished: " + lottery);
        } else {
        }
    }

    /**
     * @param lottery calculate probabilities for all possible combinations
     */
    private void calProbabilitiesForAllCombinations(Lottery lottery) {
        IntStream.range(0, 4782969)
                .mapToObj(i -> {
            String bet = int2Bet(i);
            double p = LotteryUtils.probabilityOfBet(lottery, bet);
            return new Bet(bet, p, lottery);
        }).sorted().forEachOrdered(b -> {
            System.out.println("bet=" + b.getBet() + ", p="+b.getProbability());
            betRepository.save(b);
        });
    }

    private String int2Bet(int val) {
        String s = Integer.toString(val, 3);
        if (s.length() < 14) {
            s = StringUtils.repeat('0', 14 - s.length()) + s;
        }
        return StringUtils.join(s.toCharArray(), ',').replaceAll("2", "3");
    }
}
